package org.mcache.cmd;

import org.mcache.RedisCommandProc;
import org.mcache.RedisDict;
import org.mcache.RedisObject;
import org.mcache.RedisString;

import java.util.Arrays;

/**
 * @Author: tjc
 * @description
 * @Date Created in 13:08 2022-08-14
 */
public class Commands {

    public static RedisCommandProc get = client -> {
        RedisDict dict = client.getDb().getDict();
        RedisObject value = dict.get(client.getArg(1));
        if (value == null) {
            client.addReplyNil();
            return;
        }
        if (!value.isRedisString()) {
            client.addReplyError("WRONGTYPE Operation against a key holding the wrong kind of value");
            return;
        }
        client.addReplySimpleString(value.checkRedisString().value());
    };

    public static RedisCommandProc set = client -> {
        RedisDict dict = client.getDb().getDict();
        dict.put(client.getArg(1), client.getArg(2));
        client.addReplyOk();
    };

    public static RedisCommandProc getrange = client -> {
        RedisString value = client.getArg(1).checkRedisString();
        if (!value.isRedisString()) {
            client.addReplyError("WRONGTYPE Operation against a key holding the wrong kind of value");
            return;
        }
        String value1 = value.substring(client.getArg(1).getInt(), client.getArg(2).getInt()).value();
        client.addReplyBluk(value1);
    };

    public static RedisCommandProc del = client -> {
        RedisDict dict = client.getDb().getDict();
        int i = (int) Arrays.stream(client.getArgs()).filter(key -> dict.remove(key) != null).count();
        client.addReplyInt(i);
    };

    public static RedisCommandProc getset = client -> {
        RedisDict dict = client.getDb().getDict();
        RedisObject oldValue = dict.get(client.getArg(1));
        if (oldValue != null && !oldValue.isRedisString()) {
            client.addReplyError("WRONGTYPE Operation against a key holding the wrong kind of value");
            return;
        }
        dict.put(client.getArg(1), client.getArg(2));
        if (oldValue == null) {
            client.addReplyNil();
            return;
        }
        client.addReplySimpleString(oldValue.checkRedisString().value());
        return;
    };
//
//    public static RedisCommandProc hget = (dict, args) -> {
//        RedisObject obj = dict.get(args[0]);
//        if (!obj.isRedisDict()) {
//            return ClientResponse.error("WRONGTYPE Operation against a key holding the wrong kind of value");
//        }
//        RedisDict rd = obj.checkRedisDict();
//        RedisObject value = rd.get(args[1]);
//        return client.addReplyBluk(value.checkRedisString().value());
//    };
//
//    public static RedisCommandProc hdel = (dict, args) -> {
//        RedisObject obj = dict.get(args[0]);
//        if (!obj.isRedisDict()) {
//            return ClientResponse.error("WRONGTYPE Operation against a key holding the wrong kind of value");
//        }
//        RedisDict rd = obj.checkRedisDict();
//        RedisString[] keys = Arrays.copyOfRange(args, 1, args.length);
//        int i = (int) Arrays.stream(keys).filter(key -> rd.remove(key) != null).count();
//        return ClientResponse.integer(i);
//    };
//
//
//    public static RedisCommandProc hexists = (dict, args) -> {
//        RedisObject obj = dict.getArg(args[0]);
//        if (!obj.isRedisDict()) {
//            return ClientResponse.error("WRONGTYPE Operation against a key holding the wrong kind of value");
//        }
//        RedisDict rd = obj.checkRedisDict();
//        boolean exist = rd.contains(dict.getArg(1));
//        return ClientResponse.integer(exist ? 1 : 0);
//    };
//
//
//    public static RedisCommandProc hincrby = (dict, args) -> {
//        RedisObject obj = dict.get(args[0]);
//        if (!obj.isRedisDict()) {
//            return ClientResponse.error("WRONGTYPE Operation against a key holding the wrong kind of value");
//        }
//        RedisDict rd = obj.checkRedisDict();
//        RedisObject value = rd.get(args[1]);
//        if (value == null) {
//            rd.put(args[1], args[2]);
//        } else {
//            RedisString v = value.checkRedisString();
//            if (v.isNumber()) {
//                v.inc(args[2]);
//                rd.put(args[1], v);
//            } else {
//                return ClientResponse.error("ERR hash value is not an integer");
//            }
//        }
//        return ClientResponse.integer(rd.get(args[1]).checkRedisString().getInt());
//    };
//
//    public static RedisCommandProc hgetall = (dict, args) -> {
//        RedisObject obj = dict.get(args[0]);
//        if (!obj.isRedisDict()) {
//            ClientResponse.error("WRONGTYPE Operation against a key holding the wrong kind of value");
//        }
//        RedisDict rd = obj.checkRedisDict();
//        List<ClientResponse> responses = rd.values().stream().map(v -> client.addReplyBluk(v.checkRedisString().value())).collect(Collectors.toList());
//        return ClientResponse.array(responses.toArray(new ClientResponse[responses.size()]));
//    };

    // todo
    public static RedisCommandProc hset;
    public static RedisCommandProc hmset;
    public static RedisCommandProc hmget;
    public static RedisCommandProc hlen;
    public static RedisCommandProc hvals;
    public static RedisCommandProc hincrbyfloat;
    public static RedisCommandProc hkeys;
    public static RedisCommandProc hsetnx;
    public static RedisCommandProc setnx;
    public static RedisCommandProc mset;
    public static RedisCommandProc setex;
    public static RedisCommandProc decr;
    public static RedisCommandProc decrby;
    public static RedisCommandProc strlen;
    public static RedisCommandProc mget;
    public static RedisCommandProc lset;
    public static RedisCommandProc lindex;
    public static RedisCommandProc rpush;
    public static RedisCommandProc lrange;
    public static RedisCommandProc blpop;
    public static RedisCommandProc rpoplpush;
    public static RedisCommandProc brpop;
    public static RedisCommandProc brpoplpush;
    public static RedisCommandProc lpop;
    public static RedisCommandProc rpop;
    public static RedisCommandProc linsert;
    public static RedisCommandProc sadd;
    public static RedisCommandProc spop;
    public static RedisCommandProc scard;


    public static RedisCommandProc hget;
    public static RedisCommandProc hdel;
    public static RedisCommandProc hexists;
    public static RedisCommandProc hincrby;
    public static RedisCommandProc hgetall;
}